package org.jim.server.command;

import org.jim.core.ImChannelContext;
import org.jim.core.ImPacket;
import org.jim.core.exception.ImException;
import org.jim.core.packets.Command;
import org.jim.core.packets.Message;
import org.jim.server.processor.ProtocolCmdProcessor;
import org.jim.server.processor.SingleProtocolCmdProcessor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Objects;

import static org.jim.server.processor.ProtocolCmdProcessor.RunTypeEnum.RUN_TYPE_MANUAL;

/**
 * 
 * 版本: [1.0]
 * 功能说明: 
 * @author : WChao 创建时间: 2017年9月8日 下午4:29:38
 */
public interface CmdHandler
{
	Logger logger = LoggerFactory.getLogger(CmdHandler.class);
	/**
	 * 功能描述：[命令主键]
	 * @author：WChao 创建时间: 2017年7月17日 下午2:31:51
	 * @return
	 */
	Command command();
	default ImPacket exec(ImPacket imPacket, ImChannelContext imChannelContext)  throws ImException{
		ImPacket response = handler(imPacket, imChannelContext);
		execProcess(imPacket,imChannelContext,getSingleProcessor());
		execProcess(imPacket,imChannelContext,getMultiProcessor(imChannelContext,ProtocolCmdProcessor.class));
		return response;
	}
	/**
	 * 执行处理器
	 * @param imChannelContext
	 * @param protocolCmdProcessor
	 */
	default void execProcess(ImPacket imPacket,ImChannelContext imChannelContext,ProtocolCmdProcessor protocolCmdProcessor){
		try {
			if (Objects.isNull(protocolCmdProcessor)) {
				return;
			}
			ProtocolCmdProcessor.RunTypeEnum runType = protocolCmdProcessor.getRunType() == null
					? RUN_TYPE_MANUAL : protocolCmdProcessor.getRunType();
			if (runType.equals(RUN_TYPE_MANUAL)) {
				//必须放在getMessage之前，否则会报空指针异常
				return;
			}
			Message message = protocolCmdProcessor.getMessage(imPacket, imChannelContext);
			if (Objects.isNull(message)){
				throw new ImException("缺少MessageConverter转换器，或者在处理器[" + protocolCmdProcessor.getClass().getSimpleName() + "]添加自定义getMessage方法");
			}
			switch (runType) {
				case RUN_TYPE_ASYNC:
					// 异步处理
					addQueueMsgProcessor(protocolCmdProcessor, imChannelContext, message);
					break;
				case RUN_TYPE_SYNC:
					// 自动同步处理
					protocolCmdProcessor.process(imChannelContext, message);
					break;
				default:
					break;
			}
		} catch (Exception e) {
			logger.info("执行处理器异常:{}",e);
		}
	}
	/**
	 * 处理Cmd命令
	 * @param imPacket
	 * @param imChannelContext
	 * @return
	 * @throws ImException
	 * @date 2016年11月18日 下午1:08:45
	 */
	ImPacket handler(ImPacket imPacket, ImChannelContext imChannelContext)  throws ImException;

	/**
	 * 添加消息到队列进行异步处理
	 * @param protocolCmdProcessor
	 * @param channelContext
	 * @param msg
	 */
	void addQueueMsgProcessor(ProtocolCmdProcessor protocolCmdProcessor,ImChannelContext channelContext, Message msg);
	/**
	 * 单协议业务处理器
	 * @return
	 */
	public SingleProtocolCmdProcessor getSingleProcessor();
	/**
	 * 多协议业务处理器
	 * @return
	 */
	public <T> T getMultiProcessor(ImChannelContext imChannelContext, Class<T> clazz);
}
